home *** CD-ROM | disk | FTP | other *** search
- ;
- ; routines for saving/restoring user contexts
- ;
- ; long build_context(struct context *sav):
- ; Called from an interrupt handler (such as the trap #1 routine
- ; for system calls) saves the context of the interrupted
- ; routine. Assumes that no user registers have been changed
- ; since the interrupt, and that the PC and status register
- ; are still on the stack. Returns the stack pointer being used
- ; at the time of the interrupt **in register a1**.
- ;
- ; long save_context(struct context *sav):
- ; Saves the context of the calling routine in the area pointed
- ; to by sav. Save_context always returns 0 when initially called;
- ; this is so processes can (by suitably manipulating the
- ; saved registers) tell when the return from save_context is
- ; actually caused by restoring the context, e.g.:
- ; if (save_context(sav) == 0) { <<-- L1
- ; /* do some stuff */
- ; sav.regs[D0] = 1; /* for restore context */
- ; restore_context(sav); /* goes back to L1 */
- ; }
- ; else /* this is the second time through */
- ;
- ; void restore_context(struct context *sav):
- ; Restores a context previously saved by build_context or save_context.
- ; Since the program counter is part of the context, this function
- ; will never return (it's like longjmp()).
- ;
- ; $Log: context.s,v $
- ; Revision 1.6 1992/03/31 14:02:08 AGK
- ; Fixed for real Motorola syntax (many thanks to ERS for keeping these
- ; files in step with the GAS ones).
- ;
- ; Revision 1.5 1992/03/31 13:55:28 AGK
- ; Checked in MiNT 0.93 sources
- ;
- ; Revision 1.4 1991/05/31 15:55:00 AGK
- ; Tested only a byte in the save frame, not a word (my mistake). Bumped FPU
- ; frame size up to 216 bytes, the 68882 manual is wrong (thanks Motorola!)
- ;
- ; Revision 1.3 1991/05/31 09:58:44 AGK
- ; Fixed stack frame format manipulation so we use d1, not d0, which is
- ; needed later for super/user mode determination.
- ;
- ; Revision 1.2 1991/05/31 09:48:06 AGK
- ; Changes to accomodate longer stack frames etc.
- ;
- ; Revision 1.1 1991/05/30 17:22:02 AGK
- ; Initial revision
- ;
- SECTION TEXT
-
- XDEF _build_context
- XDEF _save_context
- XDEF _restore_context
- XREF _fpu
- XREF _m68010
-
- _build_context:
- move.l a0,-(sp) ; save a0; we'll use it for scratch
- move.l 8(sp),a0 ; get address of save area
-
- ; if running with a true coprocessor we need to save the FPU state
-
- tst.w _fpu ; is there a true FPU in the system
- beq.s nofpu
- fsave 78(a0) ; save internal state frame
- tst.b 78(a0) ; if NULL frame then the FPU is not in use
- beq.s nofpu ; skip programmer's model save
- fmovem.x fp0-fp7,294(a0) ; save data registers
- fmovem.l fpcr/fpsr/fpiar,390(a0) ; and control registers
- nofpu:
- movem.l d0-d7/a0-a6,(a0) ; save registers D0-D7/A0-A6
- move.l 14(sp),66(a0) ; save PC of context
- move.w 12(sp),d0 ; get SR of context
- move.w d0,64(a0) ; save it
- tst.w ($59e).w ; test longframe (AKP)
- beq.s short1 ; short
- lea 20(sp),a1 ; else long
-
- move.w 18(sp),d1 ; fetch frame format word
- move.w d1,402(a0) ; and stash it away for later
- tst.w _m68010 ; are we on a 68010?
- bne.s short2 ; yes -- so it's a simple interrupt frame
- ; note: in order to have got to this point in the code we must be
- ; running on an 020/030 hence we can use the extra processor instructions
- bftst d1{16:4} ; is it the simple interrupt frame ?
- beq.s short2 ; yes so just dump the stack contents
- movem.l (a1)+,d1-d3 ; instruction address/4 internal words
- movem.l d1-d3,404(a0)
- bra.s short2
- short1:
- lea 18(sp),a1 ; save supervisor stack pointer
- short2: ; note that it should be pointing above the PC
- move.l a1,70(a0)
- move.l usp,a1 ; save user stack pointer
- move.l a1,60(a0)
- btst #13,d0 ; check for supervisor mode
- beq.s L_CONT1 ; user mode; we already have stack in a1
- L_SUPER1:
- ; note: this was lea a0@(18), but moving from the save state buffer
- ; means not testing longframe again. (AKP)
- move.l 70(a0),a1 ; was using super stack pointer before interrupt
- ;
- L_CONT1:
- move.l ($408).w,74(a0) ; save GEMDOS terminate vector
- move.l (sp)+,32(a0) ; save old register a0
- rts
-
- _save_context:
- move.l a0,-(sp) ; save a0
- move.l 8(sp),a0 ; get address of context save area
-
- ; if running with a true coprocessor we need to save the FPU state
-
- tst.w _fpu ; is there a true FPU in the system
- beq.s nofpu2
- fsave 78(a0) ; save internal state frame
- tst.b 78(a0) ; if NULL frame then the FPU is not in use
- beq.s nofpu2 ; skip programmer's model save
- fmovem.x fp0-fp7,294(a0) ; save data registers
- fmovem.l fpcr/fpsr/fpiar,390(a0) ; and control registers
- nofpu2:
- ; note: I am somewhat unsure of this assumption, viz that save_context
- ; can never be called in a situation where a co-processor
- ; mid-instruction stack frame would be required. I suspect this is a
- ; valid assumption, in which case the above FPU code is redundant, the
- ; next line is not however!
-
- clr.w 402(a0) ; mark as a 4 word stack frame
-
- movem.l d0-d7/a0-a6,(a0) ; save D0-D7/A0-A6
- lea 8(sp),a1
- move.l a1,70(a0) ; save supervisor stack pointer
- ; note that it should be pointing above the PC
- move.l -4(a1),66(a0) ; save PC
- move.l usp,a1
- move.l a1,60(a0) ; save user stack pointer
- move.w sr,d0
- move.w d0,64(a0) ; save status register
- move.l ($408).w,74(a0) ; save GEMDOS terminate vector
- move.l (sp)+,32(a0) ; save old a0
- moveq.l #0,d0 ; return 0
- rts
-
- _restore_context:
- ori.w #$0700,sr ; mask interrupts
- move.l 4(sp),a0 ; address of context save area
- move.l 70(a0),sp ; supervisor stack pointer
- move.l 60(a0),a1
- move.l a1,usp ; set user stack pointer
- move.l 74(a0),($408).w ; restore GEMDOS terminate vector
-
- tst.w ($59e).w ; test longframe (AKP)
- beq.s short3
-
- move.w 402(a0),d0 ; fetch frame format word
- tst.w _m68010
- bne.s just0
-
- ; again, we reach here only on an 020/030
-
- bftst d0{16:4} ; is it the simple interrupt frame ?
- beq.s just0 ; yes so just push a zero
- movem.l 404(a0),d1-d3 ; saved instruction address/4 internal words
- movem.l d1-d3,-(sp)
- just0: move.w d0,-(sp)
-
- short3:
- move.l 66(a0),-(sp) ; push the PC
- move.w 64(a0),d0 ; get status register
- move.w d0,-(sp) ; push the status register
-
- ; if running with a true coprocessor we need to restore the FPU state
-
- tst.w _fpu ; is there a true FPU in the system
- beq.s nofpu3
- tst.b 78(a0) ; if NULL frame then the FPU is not in use
- beq.s short7 ; skip programmer's model restore
- fmovem.l 390(a0),fpcr/fpsr/fpiar ; restore control registers
- fmovem.x 294(a0),fp0-fp7 ; and data registers
- short7: frestore 78(a0) ; finally the internal state
-
- nofpu3:
- movem.l (a0),d0-d7/a0-a6 ; restore registers d0-d7/a0-a6
- rte ; jump back to old context
-
- END
-